package cn.xiongxf.basic.service.impl;

import cn.xiongxf.basic.constant.VerifyCodeConstant;
import cn.xiongxf.basic.exception.BusinessException;
import cn.xiongxf.basic.service.VerifyCodeService;
import cn.xiongxf.basic.util.StrUtils;
import cn.xiongxf.basic.util.VerifyCodeUtils;
import cn.xiongxf.basic.domain.SmsDto;
import cn.xiongxf.user.domain.User;
import cn.xiongxf.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements VerifyCodeService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserMapper userMapper;

    @Override
    public String getImgVerifyCode(String key) {
        // 1.获取随机验证码
        String code = StrUtils.getComplexRandomString(4);
        // 2.保存到redis中，设置5分钟有效期
        redisTemplate.opsForValue().set(key, code, 5, TimeUnit.MINUTES);
        // 3.获取图形验证码编译的字符串
        String base64Str = VerifyCodeUtils.verifyCode(115, 40, code);
        return base64Str;
    }

    @Override
    public void sendSmsCode(SmsDto smsDto) {
        String phone = smsDto.getPhone();
        String imageCode = smsDto.getImageCode();
        String imageCodeKey = smsDto.getImageCodeKey();

        // 1.校验 - 空值校验
        if(StringUtils.isEmpty(phone)){
            throw new BusinessException("请输入手机号");
        }
        if(StringUtils.isEmpty(imageCode)){
            throw new BusinessException("请输入图形验证码");
        }
        if(StringUtils.isEmpty(imageCodeKey)){
            throw new BusinessException("请重新获取图形验证码");
        }  // 这个判断好像不对

        // 2.校验 - 手机号是否被注册 - 查询t_user表
        User user = userMapper.loadByPhone(phone);
        if (user != null){
            throw new BusinessException("该手机号已注册");
        }

        // 3.校验 - 图形验证码校验
        // 3.1.图形验证码是否过期
        Object imageCodeValue = redisTemplate.opsForValue().get(imageCodeKey);
        if (imageCodeValue == null){
            throw new BusinessException("图形验证码已过期，请重新获取");
        }
        // 3.2.图形验证码是否正确（忽略大小写）
        if(!imageCode.equalsIgnoreCase(imageCodeValue.toString())){
            throw new BusinessException("图形验证码错误，请重新输入");
        }

        // 4.生成手机验证码
        // redis存值格式：key[register:18516501320] : value[123456:28608146200]
        // 从redis中获取手机验证码，进行判断
        Object smsObj = redisTemplate.opsForValue().get(VerifyCodeConstant.REGISTER_CODE_PREFIX + phone);
        String smsCode = null;
        if (smsObj == null){
            // 如果没有，说明第一次获取手机验证码或过期 --> 重新获取
            smsCode = StrUtils.getRandomString(6);
        }else {
            // 如果有，说明没过期 --> 判断重发时间
            long nowTime = System.currentTimeMillis();
            String oldTimeStr = smsObj.toString().split(":")[1];
            long oldTime = Long.parseLong(oldTimeStr);
            if ((nowTime - oldTime) < 1*60*1000){
                throw new BusinessException("操作过于频繁，请稍后再试");
            }else {
                smsCode = smsObj.toString().split(":")[0];  //
            }
        }

        // 5.手机验证码保存到redis，需重设过期时间
        redisTemplate.opsForValue().set(VerifyCodeConstant.REGISTER_CODE_PREFIX + phone,smsCode+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);

        // 6.调用短信接口发送短信
        //SmsUtils.sendSms(phone, "您的验证码为：" + smsCode + "，请在3分钟内使用。");
        System.out.println("您的验证码为："+smsCode+"，请在3分钟内使用");
    }

    @Override
    public void binderSmsCode(SmsDto smsDto) {
        String phone = smsDto.getPhone();
        // 1.校验
        // a.非空校验
        if(StringUtils.isEmpty(phone)){
            throw new BusinessException("手机号码不能为空");
        }

        // 2.生成手机验证码
        // redis存值格式：key[register:18516501320] : value[123456:28608146200]
        // a.从redis中获取手机验证码 - 进行判断
        Object smsObj = redisTemplate.opsForValue().get(VerifyCodeConstant.BINDER_CODE_PREFIX + phone);
        String smsCode = null;
        if(smsObj == null){
            // a1.如果没有 = 第一次获取或手机验证码过期 -> 重新调用StrUtils创建新的手机验证码
            smsCode = StrUtils.getRandomString(6);
        }else{
            // a2.如果有 = 手机验证码过期没有过期 -> 判断重发时间【时间戳相减与1分钟】
            long nowTime = System.currentTimeMillis();
            String oldTimeTemp = smsObj.toString().split(":")[1];
            long oldTime = Long.parseLong(oldTimeTemp);
            if((nowTime-oldTime) < 1*60*1000){  // 重复发送短信验证码
                // a21.如果没有过重发时间 -> 抛业务异常【操作过于频繁，请稍后再试】
                throw new BusinessException("操作过于频繁，请稍后再试");
            }else{
                // a22.如果过了重发时间 -> 就使用以前的验证码
                smsCode = smsObj.toString().split(":")[0];
            }
        }

        // 3.手机验证码保存到redis - 重置3分钟有效期
        redisTemplate.opsForValue().set(VerifyCodeConstant.BINDER_CODE_PREFIX+phone,
                smsCode+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);

        // 4.调用工具类发送短信
        // SmsUtils.sendSms(phone,"你的验证码是：" + smsCode + ",请在3分钟内使用！");
        System.out.println("你的验证码是：" + smsCode + ",请在3分钟内使用！");
    }
}
